// 创建的对象可以套用一个模板的，类似于 class 类
// 工厂模式

function createPerson(name, age, job) {
  let o = new Object();

  o.name = name;

  o.age = age;

  o.job = job;

  o.sayName = () => {
    console.log(this.name);
  };

  return o;
}

// 构造函数模式
function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;

  this.sayName = function () {
    console.log(this.name);
  };
}

// 原型模式
// 理论上在原型链上定义的属性会被2个同一个function 创建出来的对象共享，但实际上对对象进行修改赋值的时候，是赋值在对象本身的，从而遮蔽了原型链上对象的影响

// 缺点，原型上引用值属性是共享的

// 2 个 对象之间 function是 共享的 ，而属性是各自的，引用值得属性也是各自的

function Person() {}

Person.prototype.name = "Nicholas";

Person.prototype.age = 29;

Person.prototype.job = "Software Engineer";

Person.prototype.sayName = function () {
  console.log(this.name);
};

// 使用class

class Person {
  constructor() {
    this.name = "Nicholas";
    this.age = 29;
    this.job = "Software Engineer";
  }

  // 会在原型上
  sayName() {
    console.log(this.name);
  }
}

// 委托模式

function create(o) {
  function Person() {}
  Person.prototype = o;
  return new Person();
}

let Person = {
  name: "Nicholas",
  age: 20,
  job: "Software Engineer",
  list: [],
  sayName() {
    return this.age;
  },
};

let person1 = create(Person);
let person2 = create(Person);
person1.age = 30;
person2.age = 40;

console.log(person1.age);
console.log(person2.age);

person1.list.push(1);
person2.list.push(2);

console.log(person1.list);

person1.list = [];

console.log(person2.list);

//  稳妥构造函数模式

function Person(name, age, obj) {
  let o = new Object();
  o.sayName = function () {
    alert(name);
  };
  o.setAge = (val) => {
    age = val;
  };
  o.getAge = () => {
    alert(age);
  };
  return o;
}

let person1 = Person("cxtao", 18, "学生");

person1.setAge(20);

person1.getAge();

let obj = {
  set a(val) {
    a = val;
  },

  get a() {
    return a;
  },
};

let person = Object.create(obj);

person.a = 10;

console.log(person.hasOwnProperty("a"));

console.log(person.a);
